// 获取页面元素
const canvas = document.getElementById('snakeCanvas');
const ctx = canvas.getContext('2d');
// 保存绿色方块位置
let greenBlock = { x: 0, y: 0 };
let lastTailDirection = { x: 0, y: 0 };

// 1. 蛇身数组
let snake = [{ x: 0, y: 0 }];

// 世界偏移量
let offsetX = 0;
let offsetY = 0;
const moveSpeed = 0.1;

// 游戏尺寸常量
const cellSize = 20;
const gap = 2;
const squareSize = cellSize + gap;

// 鼠标最新位置
let mousePosition = null;
// 蛇头目标位置
let targetPosition = null;

// 生成绿色方块的随机位置
function generateGreenBlock() {
  // 在当前可见区域内生成
  const startCol = Math.floor(offsetX / squareSize);
  const endCol = Math.floor((offsetX + canvas.width) / squareSize);
  const startRow = Math.floor(offsetY / squareSize);
  const endRow = Math.floor((offsetY + canvas.height) / squareSize);

  const colsInView = endCol - startCol;
  const rowsInView = endRow - startRow;

  let valid = false;
  while (!valid) {
    const randomCol = startCol + Math.floor(Math.random() * colsInView);
    const randomRow = startRow + Math.floor(Math.random() * rowsInView);
    greenBlock.x = randomCol * squareSize;
    greenBlock.y = randomRow * squareSize;
    valid = !snake.some(seg => seg.x === greenBlock.x && seg.y === greenBlock.y);
  }
}

function drawGrid() {
  ctx.fillStyle = '#272626';
  ctx.fillRect(0, 0, canvas.width, canvas.height);

  const alpha = 0.05;

  // 计算可见范围的网格
  const startCol = Math.floor(offsetX / squareSize);
  const endCol = Math.floor((offsetX + canvas.width) / squareSize);
  const startRow = Math.floor(offsetY / squareSize);
  const endRow = Math.floor((offsetY + canvas.height) / squareSize);

  // 绘制网格
  ctx.fillStyle = `rgba(240, 240, 220, ${alpha})`;
  for (let y = startRow; y <= endRow; y++) {
    for (let x = startCol; x <= endCol; x++) {
      const worldX = x * squareSize;
      const worldY = y * squareSize;
      const viewX = worldX - offsetX;
      const viewY = worldY - offsetY;
      ctx.fillRect(viewX, viewY, cellSize, cellSize);
    }
  }

  // 绿色方块
  ctx.fillStyle = 'rgba(144, 238, 144, 0.5)';
  ctx.fillRect(greenBlock.x - offsetX, greenBlock.y - offsetY, cellSize, cellSize);

  // 蛇身
  ctx.fillStyle = 'rgba(255, 250, 250, 0.5)';
  for (let seg of snake) {
    ctx.fillRect(seg.x - offsetX, seg.y - offsetY, cellSize, cellSize);
  }
}

function tryEat() {
  while (snake[0].x === greenBlock.x && snake[0].y === greenBlock.y) {
    const tail = snake[snake.length - 1];
    const newTail = {
      x: tail.x + lastTailDirection.x,
      y: tail.y + lastTailDirection.y
    };
    snake.push(newTail);
    generateGreenBlock();
  }
}

function animate() {
  offsetX += moveSpeed;
  offsetY += moveSpeed;

  // 检查绿色方块是否已移出屏幕
  const isOffScreen = 
    (greenBlock.x + cellSize) < offsetX || // 方块右边缘 < 屏幕左边缘
    greenBlock.x > (offsetX + canvas.width) || // 方块左边缘 > 屏幕右边缘
    (greenBlock.y + cellSize) < offsetY || // 方块下边缘 < 屏幕上边缘
    greenBlock.y > (offsetY + canvas.height);  // 方块上边缘 > 屏幕下边缘

  if (isOffScreen) {
    generateGreenBlock();
  }
  
  // 处理鼠标移动
  processMouseMove();
  
  drawGrid();
  
  requestAnimationFrame(animate);
}

window.addEventListener('mousemove', (event) => {
  const rect = canvas.getBoundingClientRect();
  const worldMouseX = (event.clientX - rect.left) + offsetX;
  const worldMouseY = (event.clientY - rect.top) + offsetY;

  const newHeadX = Math.floor(worldMouseX / squareSize) * squareSize;
  const newHeadY = Math.floor(worldMouseY / squareSize) * squareSize;

  // 更新鼠标位置
  mousePosition = { x: newHeadX, y: newHeadY };
});

// 处理鼠标移动
function processMouseMove() {
  if (!mousePosition) return;
  
  // 设置蛇头目标位置
  targetPosition = { x: mousePosition.x, y: mousePosition.y };
  
  // 如果蛇头已经在目标位置，无需处理
  if (snake[0].x === targetPosition.x && snake[0].y === targetPosition.y) {
    return;
  }

  // 计算蛇头到目标点的方向
  let dx = 0, dy = 0;
  const maxSteps = 3; // 每帧最多移动步数，提高响应速度
  
  for (let step = 0; step < maxSteps; step++) {
    // 检查是否已到达目标位置
    if (snake[0].x === targetPosition.x && snake[0].y === targetPosition.y) {
      break;
    }
    
    // 计算当前步的移动方向
    if (targetPosition.x > snake[0].x) dx = squareSize;
    else if (targetPosition.x < snake[0].x) dx = -squareSize;
    else dx = 0;
    
    if (targetPosition.y > snake[0].y) dy = squareSize;
    else if (targetPosition.y < snake[0].y) dy = -squareSize;
    else dy = 0;

    const newHeadX = snake[0].x + dx;
    const newHeadY = snake[0].y + dy;

    if (snake.length > 1) {
      const tail = snake[snake.length - 1];
      const prev = snake[snake.length - 2];
      lastTailDirection.x = tail.x - prev.x;
      lastTailDirection.y = tail.y - prev.y;
    } else {
      lastTailDirection.x = snake[0].x - newHeadX;
      lastTailDirection.y = snake[0].y - newHeadY;
    }

    for (let i = snake.length - 1; i > 0; i--) {
      snake[i].x = snake[i - 1].x;
      snake[i].y = snake[i - 1].y;
    }
    snake[0].x = newHeadX;
    snake[0].y = newHeadY;

    tryEat();
  }
}

function resizeCanvas(){
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
}

window.addEventListener('resize', resizeCanvas);

function initSnakeGame() {
  resizeCanvas();
  snake = [{ x: 0, y: 0 }];
  offsetX = 0;
  offsetY = 0;
  generateGreenBlock();
  tryEat();
}

initSnakeGame();
requestAnimationFrame(animate);